package birdsVSZombiesClient;
import com.esotericsoftware.kryonet.Client;

import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PVector;
import shared.BVZClientToServerMessages;
import shared.BVZConstants;


/**
 * @author yangliu
 *
 */
public class GestureControl {
	
	public static PApplet parent;
	
	public GBoundingBox gBoundingBox;
	
	public PVector stdDvPos;
	public PVector stdDvOffset;
	public float stdDvRadius;
	public int stdDvColor;
	
	private boolean isHolding;
	private int holdThreshold;
	
	public GestureControl(){
		gBoundingBox = new GBoundingBox();
		isHolding = false;
		holdThreshold = 40;
		
		stdDvColor = parent.color(0, 255, 0, 200);
	}
	
	public void standardDeviationCircle(float stdDv, PVector center, PVector kOffset){
//		parent.println(stdDv);
		stdDvPos = center;
		stdDvOffset = kOffset;
		stdDvRadius = stdDv;
		parent.fill(stdDvColor);
		parent.strokeWeight(2);
		parent.ellipseMode(PConstants.CENTER);
		parent.ellipse(center.x+kOffset.x, center.y+kOffset.y, stdDv*2, stdDv*2);
		
	}
	
	public GBoundingBox getBoundingBox(){
		return gBoundingBox;
	}
	
	public void detect(int clientStat, Client bvzClient, int playerRole){
		if(stdDvRadius < holdThreshold){
			if(!isHolding){
				stdDvColor = parent.color(255, 0, 0, 200);
				gestureHold(clientStat, bvzClient, playerRole);
			}
			else{
				gestureDragged(clientStat, bvzClient, playerRole);
			}
			isHolding = true;
		}
		
		if(stdDvRadius > holdThreshold){
			if(isHolding){
				isHolding = false;
				stdDvColor = parent.color(0, 255, 0, 200);
				gestureReleased(clientStat, bvzClient, playerRole);
			}
		}
		
	}
	
	
	//	Gesture Events
	public void gestureHold(int clientStat, Client bvzClient, int playerRole){
		switch (clientStat) {
			case 3:
				BVZClientToServerMessages ctsMsg = makeClientMessage(BVZConstants.CLIENTRUNNINGPHYS, playerRole, BVZConstants.MOUSEPRESSED);
				bvzClient.sendTCP(ctsMsg);
				break;
	
			default:
				break;
		}
	}
	
	public void gestureDragged(int clientStat, Client bvzClient, int playerRole){
		switch (clientStat) {
			case 3:
				BVZClientToServerMessages ctsMsg = makeClientMessage(BVZConstants.CLIENTRUNNINGPHYS, playerRole, BVZConstants.MOUSEDRAGGED);
				bvzClient.sendTCP(ctsMsg);
				
				break;
			default:
				break;
		}
	}
	
	public void gestureReleased(int clientStat, Client bvzClient, int playerRole){
		switch (clientStat) {
			case 3:
				BVZClientToServerMessages ctsMsg = makeClientMessage(BVZConstants.CLIENTRUNNINGPHYS, playerRole, BVZConstants.MOUSERELEASED);
				bvzClient.sendTCP(ctsMsg);
				break;
				
			default:
				break;
		}
	}
	
	/**
	 * Construct the message which will be sent to the server.
	 * @param _clientStat 	The status of the client.
	 * @param _playerRole	The role of the player.
	 * @param _mouseStat 	The status of the mouse. 
	 * @return The Json representation of the message.
	 */
	public BVZClientToServerMessages makeClientMessage(int _clientStat, int _playerRole, int _mouseStat){
		BVZClientToServerMessages msg = new BVZClientToServerMessages(_clientStat, _playerRole, _mouseStat, stdDvPos.x + stdDvOffset.x, stdDvPos.y + stdDvOffset.y);
		return msg;
	}
	
	/**
	 *	The bounding box of the gesture
	 *	
	 */
	public class GBoundingBox{
		private PVector gBoundingBoxMin;
		private PVector gBoundingBoxMax;
		private PVector centroid;
		
		private int boxColor;
		private float boxArea;
		private boolean isDraw;
		
		private boolean initUpdate;
		
		public GBoundingBox(){
			gBoundingBoxMin =  new PVector(0, 0);
			gBoundingBoxMax = new PVector(0, 0);
			centroid = new PVector(0, 0);
			
			boxColor = parent.color(100, 250, 50, 100);
			boxArea = 0;
			isDraw = true;
			initUpdate = true;
		}
		
		public void update(int x, int y){
			if (initUpdate == true){
				gBoundingBoxMin.x = gBoundingBoxMax.x = x;
				gBoundingBoxMin.y = gBoundingBoxMax.y = y;
				
				initUpdate = false;
			} 
			else {
				if (x < gBoundingBoxMin.x){
					gBoundingBoxMin.x = x;	
				}
				if (x > gBoundingBoxMax.x){
					gBoundingBoxMax.x = x;	
				}
				if (y < gBoundingBoxMin.y){
					gBoundingBoxMin.y = y;
				}
				if (y > gBoundingBoxMax.y){
					gBoundingBoxMax.y = y;
				}
			}
			
			centroid = PVector.add(gBoundingBoxMin, gBoundingBoxMax);
			
			centroid.div(2);
			
		}
		
		public float getArea(){
			float width = parent.abs(gBoundingBoxMax.x - gBoundingBoxMin.x);
			float height = parent.abs(gBoundingBoxMax.y - gBoundingBoxMin.y);
			
			return width*height;
		}
		
		public void draw(){
			if(isDraw){
				//	Draw the bounding box
				parent.rectMode(PConstants.CORNERS);
				
				parent.fill(boxColor);
				parent.strokeWeight(2);
				parent.rect(gBoundingBoxMin.x, gBoundingBoxMin.y, gBoundingBoxMax.x, gBoundingBoxMax.y);
				
				parent.ellipseMode(PConstants.CENTER);
				parent.fill(255, 0, 0, 160);
				parent.ellipse(centroid.x, centroid.y, 25, 25);
				
			}
		}
		
		/**
		 *	Set whether to draw the bounding box or not
		 */
		public void setDrawable(boolean d){
			isDraw = d;
		}
		
		public void setInitUpdate(boolean i){
			initUpdate = i;
		}
		
		public void setColor(int r, int g, int b, int a){
			boxColor = parent.color(r, g, b, a);
		}
		
		public PVector getMin(){
			return gBoundingBoxMin;
		}
		
		public PVector getMax(){
			return gBoundingBoxMax;
		}
		
		public void setMinX(int _x){
			gBoundingBoxMin.x = _x;
		}
		
		public void setMinY(int _y){
			gBoundingBoxMin.y = _y;
		}
		
		public void setMaxX(int _x){
			gBoundingBoxMax.x = _x;
		}
		
		public void setMaxY(int _y){
			gBoundingBoxMax.y = _y;
		}
		
	}
	
}
